package com.yutian.selfservice.config;

import com.yutian.selfservice.support.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

/**
 * 全局异常处理
 * @author zuoqiwen
 * @version 1.0
 * @date 2021-08-04
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 请求方式错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public Result handleException(HttpRequestMethodNotSupportedException e) {
        return Result.fail("不支持' " + e.getMethod() + "'请求");
    }

    /**
     * 参数校验错误，参数不符合要求  @RequestBody @validate
     *
     * @param e
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class,BindException.class})
    public Result handleException(BindException e) {
        String message =
                e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(";"));
        return Result.paramError("参数错误：" + message);
    }
    /**
     * 参数校验错误，参数不符合要求  @RequestParam @validate
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result ConstraintViolationExceptionHandler(ConstraintViolationException e) {
        String message =
                e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(","));
        return Result.paramError("参数错误：" + message);
    }
    /**
     * 参数异常  手动抛出
     *
     * @param e
     * @return
     */
    @ExceptionHandler({IllegalArgumentException.class})
    public Result IllegalArgumentException(IllegalArgumentException e) {
        return Result.paramError(e.getMessage());
    }

    /**
     * @param e
     * @return
     * @RequestBody json转换成对象时json解析异常
     */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public Result handleException(HttpMessageNotReadableException e) {
        return Result.paramError("json格式错误：" + e.getMessage());
    }


    @ExceptionHandler({RuntimeException.class})
    public Result runtimeException(RuntimeException e) {
        log.error(e.getMessage(), e);
        return Result.fail("系统运行时异常");
    }

    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        log.error(e.getMessage(), e);
        return Result.fail("服务器错误");
    }

    @ExceptionHandler({ResourceAccessException.class})
    public Result handleException(ResourceAccessException e) {
        log.error("调用内联网服务获取数据失败：" + e.getMessage(), e);
        return Result.paramError("调用内联网服务获取数据失败：" + e.getMessage());
    }

    @ExceptionHandler({RestClientException.class})
    public Result handleException(RestClientException e) {
        log.error("调用内联网服务失败：" + e.getMessage(), e);
        return Result.paramError("调用内联网服务失败：" + e.getMessage());
    }
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public Result missingServletRequestParameterException(MissingServletRequestParameterException e) {
        String message = "参数错误:"+e.getParameterName()+"不能为空";
        return Result.paramError(message);
    }
    @ExceptionHandler({MaxUploadSizeExceededException.class})
    public Result maxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        String message = null;
        if (e.getCause().getCause() instanceof FileSizeLimitExceededException) {
            long size = ((FileSizeLimitExceededException) e.getCause().getCause()).getPermittedSize()/1024/1024;
            message = "上传文件过大[单文件大小不得超过"+size+"M]";
        } else if (e.getCause().getCause() instanceof SizeLimitExceededException) {
            long size = ((SizeLimitExceededException) e.getCause().getCause()).getPermittedSize()/1024/1024;
            message = "上传文件过大[总上传文件大小不得超过"+size+"M]";
        } else {
            message = "上传文件失败";
        }
        return Result.paramError(message);
    }

}
